home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Monster Media 1996 #15
/
Monster Media Number 15 (Monster Media)(July 1996).ISO
/
prog_bas
/
qbsvga.zip
/
QBSVGA.BAS
< prev
next >
Wrap
BASIC Source File
|
1996-04-22
|
26KB
|
862 lines
'
' Subroutine BSCREEN emulates the function of QB's SCREEN statement.
' It uses subroutine FINDVESA to find a video mode supported by a VESA
' bios that corresponds to a "QB-type" mode specified by MODE. The
' resolutions for each supported MODE integer are given below.
'
' MODE = 14: 640 x 480 x 256
' MODE = 15: 800 x 600 x 16
' MODE = 16: 800 x 600 x 256
' MODE = 17: 1024 x 768 x 16
' MODE = 18: 1024 x 768 x 256
' MODE = 19: 1200 x 1024 x 16
' MODE = 20: 1200 x 1024 x 256
' MODE = 21: 1600 x 1200 x 16
' MODE = 22: 1600 x 1200 x 256
' MODE = 23: 132 x 25 x 16 (text)
' MODE = 24: 132 x 43 x 16 (text)
' MODE = 25: 132 x 50 x 16 (text)
'
' These routines should not be used with modes not specified here. Mode
' 0 is an allowable input; it corresponds to QB's SCREEN 0 and gets
' translated here to bios mode 3. (Except for more colors, I'm not aware
' of any higher modes, anyway, and why would you want to use these
' routines with the lower modes? QB's SCREEN statement will do that.) If
' a mode with the desired resolution and colors cannot be found, a mode
' will still be selected if one can be found with the desired resolution
' and *more* colors than necessary.
'
' The first four inputs are just as would be used with QB's SCREEN
' statement. INREGS and OUTREGS are register variables defined as such
' in the MAIN routine. (See REGTYPE.INC. In the CALLs to these routines,
' you only need the "INREGS" and "OUTREGS"; you don't need the "AS
' REGISTERS" clauses there.) Unlike the SCREEN statement, all parameters
' much be specified in the CALL. If the input video mode is the one that
' is already in effect, BSCREEN can be used to simply change default
' colors or displayed/active pages. (You might want to use subroutine
' BCOLOR for the former purpose.) BSCREEN should be called before any of
' the other routines are called.
'
SUB BSCREEN(MODE,CL,APAGE,VPAGE,INREGS AS REGISTERS,OUTREGS AS REGISTERS)
DIM CMODE AS INTEGER
'
' Use variable aliases in case inputs were numeric literals in CALL
' statement. Bios page numbers are zero-based.
'
C=CL : AP=APAGE-1 : VP=VPAGE-1
'
' Get current video mode. If it is same as one being set, no mode change
' is made. The routine is just being used to change default colors
' (subroutine BCOLOR is simpler to use for that purpose) or pages. (The
' value of CMODE may get changed after VESA-awareness is determined.)
'
INREGS.AX=&HF00
CALL INTERRUPTX(&H10,INREGS,OUTREGS)
CMODE=OUTREGS.AX AND &HFF
'
' Set visible page.
'
INREGS.AX=VP+1280
CALL INTERRUPTX(&H10,INREGS,OUTREGS)
'
' Store active page and default color in global variables.
'
ACPAGE=AP
IF C<=0 THEN C=7
DEFLTC=C
'
' Make correlation between "QB-type" modes and resolution of bios mode to
' be searched for. (Set default mode data in case invalid mode was input.)
'
HR=800 : VR=600 : NC=16
IF MODE=14 THEN HR=640 : VR=480
IF MODE=15 OR MODE=16 THEN HR=800 : VR= 600
IF MODE=17 OR MODE=18 THEN HR=1024 : VR=768
IF MODE=19 OR MODE=20 THEN HR=1280 : VR=1024
IF MODE=21 OR MODE=22 THEN HR=1600 : VR=1200
IF MODE=23 THEN VR=25
IF MODE=24 THEN VR=43
IF MODE=25 THEN VR=50
IF MODE=0 OR MODE=15 OR MODE=17 OR MODE=19 OR MODE=21 OR MODE>22 THEN NC=16
IF MODE=14 OR MODE=16 OR MODE=18 OR MODE=20 OR MODE=22 THEN NC=256
IF MODE=23 OR MODE=24 OR MODE=25 THEN HR=132
'
' Define global resolution limits (zero-based) and viewport defaults.
'
HMAX=HR-1 : VMAX=VR-1 : VXL=0 : VYL=0 : VXR=HMAX : VYR=VMAX
'
' Set VCOL to a negative number so other routines can tell that BVIEW
' wasn't called yet.
'
VCOL=-1
IF MODE<>0 THEN
'
' SCREEN is not being reset to text mode. Find VESA mode with desired
' resolution. If FINDVESA can't find a requisite VESA mode, whether
' because system isn't VESA-aware or other reasons, BMODE is returned as
' -1. (If system is detected as VESA aware, an "error code" of 0 is
' defined via VESSUP variable. If VESA cannot be detected, VESSUP is set
' to unity.) Before using FINDVESA, however, look for overriding bios
' mode definition via DOS environment variable. (This environment
' is SET with the syntax "MODE##=bios-mode", where ## is the two-digit
' QB-type mode integer that corresponds to bios-mode.)
'
QBMODE$="MODE"+LTRIM$(RTRIM$(STR$(MODE)))
EMODE$=MID$(LTRIM$(ENVIRON$(QBMODE$)),1,80)
BMODE=VAL("&H0"+EMODE$)
IF BMODE=0 THEN
'
' "MODE##" environment variable didn't exist for input QB-type mode.
'
CALL FINDVESA(BMODE,HR,VR,NC,INREGS,OUTREGS)
'
' Except for text mode 3, there are no bios modes less than 4 that are
' of concern here. (There aren't likely any below 13h of any importance.
' I'm just taking into account "wierd" video adapters, such as mine, which
' will do a hex mode B.)
'
IF BMODE>=4 THEN
'
' VESA mode was found, hence, system is VESA-aware. Redetermine current
' video mode.
'
INREGS.AX=&H4F03
CALL INTERRUPTX(&H10,INREGS,OUTREGS)
CMODE=OUTREGS.BX
IF CMODE<>BMODE THEN
'
' VESA mode was found and it is different from current mode; change video
' mode.
'
INREGS.AX=&H4F02
INREGS.BX=BMODE
CALL INTERRUPTX(&H10,INREGS,OUTREGS)
END IF
ELSE
'
' VESA mode couldn't be found. Assume "OEM SVGA" and ask user for
' hexadecimal mode integer that corresponds to desired video mode. Set
' VESSUP according to value of input bios mode. (Put screen in standard
' QB text mode so prompt can be seen in case it was already in some
' QB-unreadable graphics screen.)
'
INREGS.AX=3
CALL INTERRUPTX(&H10,INREGS,OUTREGS)
SCREEN 0,C,1,1
RES$=LTRIM$(RTRIM$(STR$(HR)))+" x "+LTRIM$(RTRIM$(STR$(VR)))+" x "
RES$=RES$+LTRIM$(RTRIM$(STR$(NC)))
PRINT
PRINT " Couldn't find VESA mode giving resolution ";RES$;". What"
PRINT "hexadecimal bios mode integer gives you this resolution? (Press ENTER"
PRINT "to stop.)"
LINE INPUT M$
M$=RTRIM$(LTRIM$(M$))
IF M$="" THEN STOP
'
' Video mode is changed regardless of its present state when mode had to
' be prompted for. (Even if the above text-mode change hadn't occurred,
' the prompt for the mode needs to be cleared.)
'
VESSUP=1
INREGS.AX=VAL("&H"+M$)
'
' Use VESA call to set video mode if it is 100h or above. Otherwise,
' use standard bios call.
'
IF INREGS.AX>255 THEN
VESSUP=0
INREGS.BX=INREGS.AX
INREGS.AX=&H4F02
END IF
CALL INTERRUPTX(&H10,INREGS,OUTREGS)
END IF
ELSE
'
' "MODE##" environment variable exists for desired mode. Set VESSUP
' according to value of bios mode.
'
VESSUP=1 : IF BMODE>255 THEN VESSUP=0
'
' Re-acquire and test current video mode before changing it.
'
IF VESSUP=1 THEN
INREGS.AX=&HF00
CALL INTERRUPTX(&H10,INREGS,OUTREGS)
CMODE=OUTREGS.AX AND &HFF
INREGS.AX=BMODE
ELSE
INREGS.AX=&H4F03
CALL INTERRUPTX(&H10,INREGS,OUTREGS)
CMODE=OUTREGS.BX
INREGS.AX=&H4F02
INREGS.BX=BMODE
END IF
IF CMODE<>BMODE THEN CALL INTERRUPTX(&H10,INREGS,OUTREGS)
END IF
ELSE
'
' SCREEN 0 is being emulated. Use what should be a standard text mode
' for any SVGA system. (This mode is also set regardless of whether or
' not the video state is already there.)
'
INREGS.AX=3
CALL INTERRUPTX(&H10,INREGS,OUTREGS)
'
' Just to be safe, make sure QB knows what screen mode it's in. (The
' above call to interrupt 10 could probably be skipped, but QB's SCREEN 0
' by itself doesn't necessarily leave you in the text mode you want when
' the screen isn't initially in a mode that QB recognizes.)
'
SCREEN 0,C,1,1
END IF
END SUB
'
' This subroutine returns the VESA bios MODE integer (decimal) that has
' resolution HR x VR x NC, as input via the parameter list. If no such
' mode can be found, MODE is returned as -1. (If it finds a mode with
' the desired horizontal HR and vertical VR resolution but with more than
' NC colors, the mode is considered valid and is returned in MODE. (It
' will first try to find a mode with NC colors.)) Also, it only looks for
' graphics modes.
'
' To qualify as a valid, the mode must be supported by both hardware and
' bios. (FINDVESA is usually called by BSCREEN. There is not much reason
' to call it directly.)
'
SUB FINDVESA(MODE,HR,VR,NC,INREGS AS REGISTERS,OUTREGS AS REGISTERS)
DIM VESA(1 TO 64) AS LONG,BYTE AS LONG,MD(1 TO 257) AS INTEGER,COLORS(1 TO 256)
SM=VARSEG(VESA(1)) : OS=VARPTR(VESA(1))
'
' Set VESSUP to unity in case VESA bios cannot be detected.
'
VESSUP=1
'
' Confirm VESA support and get pointer to list of supported VESA modes.
'
INREGS.AX=&H4F00
INREGS.ES=CINT(SM)
INREGS.DI=CINT(OS)
CALL INTERRUPTX(&H10,INREGS,OUTREGS)
DEF SEG=SM
T$=CHR$(PEEK(OS))+CHR$(PEEK(OS+1))+CHR$(PEEK(OS+2))+CHR$(PEEK(OS+3))
IF T$<>"VESA" THEN GOTO NOSUP
'
' VESA = VESA bios version number.
'
VESA=PEEK(OS+5)+PEEK(OS+4)/10
PSM=PEEK(OS+16)+256*PEEK(OS+17) : POF=PEEK(OS+14)+256*PEEK(OS+15)
'
' Look for video mode that supports desired resolution.
'
' NMODES counts number of modes (possibly with different colors) with
' desired resolution.
'
NMODES=1
NEWMODE:
DEF SEG=PSM
MD(NMODES)=PEEK(POF)+256*PEEK(POF+1) : POF=POF+2
IF MD(NMODES)=-1 THEN GOTO NOSUP
INREGS.AX=&H4F01
INREGS.CX=MD(NMODES)
INREGS.ES=CINT(SM)
INREGS.DI=CINT(OS)
CALL INTERRUPTX(&H10,INREGS,OUTREGS)
DEF SEG=SM
'
' First byte at segment SM stores "support information" about mode under
' analysis.
'
BYTE=CLNG(PEEK(OS)+256*PEEK(OS+1))
B$=LTRIM$(RTRIM$(BIN$(BYTE)))
'
' Bits 0 and 2 indicate support (or lack of it) in hardware and BIOS.
'
HARD$=MID$(B$,16,1)
BIOS$=MID$(B$,14,1)
IF HARD$="0" OR BIOS$="0" THEN GOTO NEWMODE
'
' Bit 4 indicates graphics or text mode.
'
GMSW$=MID$(B$,12,1)
'
' Bit 1 indicates the presence of extended information. If no extended
' information is available for this mode, it cannot be determined that
' it supports the required HR x VR resolution.
'
EXTINF$=MID$(B$,15,1)
IF EXTINF$="0" THEN GOTO NEWMODE
'
' Character sizes are needed to correct stored resolution data for some
' VESA bioses.
'
HS=PEEK(OS+22) : VS=PEEK(OS+23)
HRM=PEEK(OS+18)+256*PEEK(OS+19) : VRM=PEEK(OS+20)+256*PEEK(OS+21)
IF VESA<1.2 THEN
IF GMSW$="0" THEN HRM=HRM/HS : VRM=VRM/VS
IF (MD(NMODES)>=0 AND MD(NMODES)<=6) OR MD(NMODES)=13 THEN VRM=VRM/2
IF MD(NMODES)=14 OR MD(NMODES)=19 THEN VRM=VRM/2
END IF
IF HR<>HRM OR VR<>VRM THEN GOTO NEWMODE
COLORS(NMODES)=2!^CSNG(PEEK(OS+25))
'
' Get all modes with required resolution, regardless of color. (Later
' on the one with NC colors, if it exists, will be chosen. (But the
' possibility that the one with the right number of colors will be found
' first is taken into account.))
'
IF COLORS(NMODES)=NC THEN GOTO RETMODE
IF NMODES<256 THEN NMODES=NMODES+1 : GOTO NEWMODE
RETMODE:
'
' Since VESA was detected, store corresponding error code.
'
VESSUP=0
FOR I=1 TO NMODES
K=I
IF COLORS(I)=NC THEN MODE=MD(I) : GOTO QUIT
NEXT I
FOR I=1 TO NMODES
K=I
IF COLORS(I)>NC THEN MODE=MD(I) : GOTO QUIT
NEXT I
NOSUP:
'
' Requisite VESA mode couldn't be found. Return negative mode value as
' switch for calling routine to recognize that fact.
'
MODE=-1
QUIT:
DEF SEG
END SUB
'
' This is a "functionized" version of code extracted from a more general
' numeric base conversion program by Robert B. Relf, (C) 1984. This just
' uses the part of Mr. Relf's code that converts decimal to binary.
'
FUNCTION BIN$(NUM AS LONG)
DIM X AS INTEGER
IF NUM<0 THEN NUM=NUM+65536&
BIN1$=""
FOR X=15 TO 0 STEP -1
IF NUM>=(2^X) THEN
BIN1$=BIN1$+"1"
NUM=NUM-(2^X)
ELSE
BIN1$=BIN1$+"0"
END IF
NEXT X
BIN1$=LEFT$(BIN1$,8)+RIGHT$(BIN1$,8)
BIN$=BIN1$
END FUNCTION
'
' This subroutine is the analog of QB's intrinsic PSET statement.
'
SUB BPSET(XCOORD,YCOORD,CL,INREGS AS REGISTERS,OUTREGS AS REGISTERS)
'
' Alias inputs in case they were input as numeric literals (which also
' serves to convert the viewport coordinates to screen coordinates).
'
C=CL : X=XCOORD+VXL : Y=YCOORD+VYL
'
' Enforce viewport constraints.
'
IF X<VXL THEN X=VXL
IF Y<VYL THEN Y=VYL
IF X>VXR THEN X=VXR
IF Y>VYR THEN Y=VYR
INREGS.BX=CINT(ACPAGE)
IF C<0 THEN C=DEFLTC
INREGS.AX=3072+CINT(C)
INREGS.CX=CINT(X)
INREGS.DX=CINT(Y)
CALL INTERRUPTX(&H10,INREGS,OUTREGS)
END SUB
'
' Subroutine BLINE emulates the functionality of QB's LINE statement.
' Except for LINE's "()" and "-" notation, BLINE's syntax is pretty much
' the same as LINE's. The line style option is not supported here and
' the parameter specifying whether the drawn object is a line, box, or
' filled box ("L", "B", or "BF") must be in quotes in the CALL statement.
' Other than that, all parameters must be specified in the CALL. As
' usual, INREGS and OUTREGS are register variables.
'
SUB BLINE(XLC,YLC,XRC,YRC,CL,BOX$,INREGS AS REGISTERS,OUTREGS AS REGISTERS)
'
' Alias input variables in case they were input as numeric literals and
' then get page to draw on.
'
B$=UCASE$(BOX$) : C=CL : XL=XLC : YL=YLC : XR=XRC : YR=YRC
'
' Enforce viewport constraints.
'
XL=XL+VXL : YL=YL+VYL : XR=XR+VXL : YR=YR+VYL
IF XL<VXL THEN XL=VXL
IF YL<VYL THEN YL=VYL
IF XR>VXR THEN XR=VXR
IF YR>VYR THEN YR=VYR
'
' Set color to default color if it was input as negative.
'
IF C<0 THEN C=DEFLTC
'
' If box isn't to be drawn, draw line.
'
IF B$<>"B" AND B$<>"BF" THEN
IF XL<>XR THEN
'
' Draw nonvertical line.
'
NPIX=CINT(SQR((XR-XL)^2+(YR-YL)^2)+.501)
DX=(XR-XL)/(NPIX-1)
FOR I=1 TO NPIX
X=(I-1)*DX+XL
Y=(YR-YL)*(X-XL)/(XR-XL)+YL
INREGS.AX=3072+CINT(C)
INREGS.BX=CINT(ACPAGE)
INREGS.CX=CINT(X)
INREGS.DX=CINT(Y)
CALL INTERRUPTX(&H10,INREGS,OUTREGS)
NEXT I
ELSE
'
' Draw vertical line.
'
FOR Y=YL TO YR
INREGS.AX=3072+CINT(C)
INREGS.BX=CINT(ACPAGE)
INREGS.CX=CINT(XL)
INREGS.DX=CINT(Y)
CALL INTERRUPTX(&H10,INREGS,OUTREGS)
NEXT Y
END IF
'
' Draw box.
'
ELSE
FOR Y=YL TO YR
INREGS.AX=3072+CINT(C)
INREGS.BX=CINT(ACPAGE)
INREGS.CX=CINT(XL)
INREGS.DX=CINT(Y)
CALL INTERRUPTX(&H10,INREGS,OUTREGS)
NEXT Y
FOR X=XL+1 TO XR
INREGS.AX=3072+CINT(C)
INREGS.BX=CINT(ACPAGE)
INREGS.CX=CINT(X)
INREGS.DX=CINT(YR)
CALL INTERRUPTX(&H10,INREGS,OUTREGS)
NEXT X
FOR Y=YR-1 TO YL STEP -1
INREGS.AX=3072+CINT(C)
INREGS.BX=CINT(ACPAGE)
INREGS.CX=CINT(XR)
INREGS.DX=CINT(Y)
CALL INTERRUPTX(&H10,INREGS,OUTREGS)
NEXT Y
FOR X=XR-1 TO XL+1 STEP -1
INREGS.AX=3072+CINT(C)
INREGS.BX=CINT(ACPAGE)
INREGS.CX=CINT(X)
INREGS.DX=CINT(YL)
CALL INTERRUPTX(&H10,INREGS,OUTREGS)
NEXT X
END IF
'
' Fill box if told to do so.
'
IF B$="BF" THEN
FOR Y=YL+1 TO YR-1
FOR X=XL+1 TO XR-1
INREGS.AX=3072+CINT(C)
INREGS.BX=CINT(ACPAGE)
INREGS.CX=CINT(X)
INREGS.DX=CINT(Y)
CALL INTERRUPTX(&H10,INREGS,OUTREGS)
NEXT X
NEXT Y
END IF
END SUB
'
' Subroutine BCIRCLE emulates QB's CIRCLE statement. The center is at
' (XCNT,YCNT), the radius is RAD, the color is CL, the starting angle is
' ST (radians), the ending angle is EN radians, and ASP is the aspect.
' (As always, all parameters must be specified.) If EN = ST, a circle/
' ellipse is drawn.
'
SUB BCIRCLE(XCNT,YCNT,RAD,CL,ST,EN,ASP,INREGS AS REGISTERS,OUTREGS AS REGISTERS)
'
' Use double precision calculations, set drawing page, and use default
' color if input color is negative.
'
DIM PI AS DOUBLE,A AS DOUBLE,DA AS DOUBLE,X AS DOUBLE,Y AS DOUBLE,XC AS DOUBLE
DIM YC AS DOUBLE,R AS DOUBLE,ASPECT AS DOUBLE,SA AS DOUBLE,EA AS DOUBLE
R=CDBL(RAD) : ASPECT=CDBL(ASP) : YC=CDBL(YCNT) : XC=CDBL(XCNT) : EA=CDBL(EN)
SA=CDBL(ST) : C=CL
IF ASPECT<0 THEN ASPECT=1#
IF C<0 THEN C=DEFLTC
'
' Define PI and test for/define circle condition.
'
PI=4#*ATN(1#)
IF EA=SA THEN EA=SA+2#*PI
DA=(EA-SA)/2999#
'
' Draw arc/circle.
'
FOR I=1 TO 3000
A=DA*CDBL(I-1)+SA
X=XC+R*COS(A) : Y=YC-R*SIN(A)
IF ASPECT>1 THEN X=XC+R*COS(A)/ASPECT
IF ASPECT<1 THEN Y=YC-R*ASPECT*SIN(A)
'
' Enforce viewport constraints.
'
X=X+CDBL(VXL) : Y=Y+CDBL(VYL)
IF X<VXL THEN X=VXL
IF Y<VYL THEN Y=VYL
IF X>VXR THEN X=VXR
IF Y>VYR THEN Y=VYR
INREGS.AX=3072+CINT(C)
INREGS.BX=CINT(ACPAGE)
INREGS.CX=CINT(X)
INREGS.DX=CINT(Y)
CALL INTERRUPTX(&H10,INREGS,OUTREGS)
NEXT I
END SUB
'
' This is the analog of QB's CLS command. BCLS clears the screen by
' putting it in the same video mode that it's already in. CLSMODE = 0
' yields an effect equivalent to QB's CLS 0 and CLSMODE = 1 is like CLS 1.
' (The CLS 1 emulation does not involve the above mentioned mode change
' operation. It uses the somewhat slower method of drawing a filled box
' with color 0.)
'
'
SUB BCLS(CLSMODE,INREGS AS REGISTERS,OUTREGS AS REGISTERS)
'
' Look for CLS 0/1 condition. (If no viewport was defined, CLSMODE = 1
' will be treated as CLS 0.)
'
IF CLSMODE<>1 OR VCOL<0 THEN
'
' How video mode is detected and changed depends on whether or not VESA
' bios is present.
'
IF VESSUP=1 THEN GOTO NOVESA
INREGS.AX=&H4F03
CALL INTERRUPTX(&H10,INREGS,OUTREGS)
INREGS.AX=&H4F02
INREGS.BX=OUTREGS.BX
GOTO SETMODE
NOVESA:
INREGS.AX=&HF00
CALL INTERRUPTX(&H10,INREGS,OUTREGS)
INREGS.AX=OUTREGS.AX AND &HFF
SETMODE:
CALL INTERRUPTX(&H10,INREGS,OUTREGS)
'
' Reset viewport defaults. (Turn off viewport in case it was defined.)
'
VCOL=-1 : VXL=0 : VYL=0 : VXR=HMAX : VYR=VMAX
ELSE
CALL BVIEW(VXL,VYL,VXR,VYR,VCOL,VBORD,INREGS,OUTREGS)
END IF
END SUB
'
' This subroutine sets the default color to CL. (In spite of the "B"
' leading the subroutine name, there is no bios call involved here.
' Hence, INREGS and OUTREGS need and must not be passed to this routine.)
' Unlike BSCREEN, BCOLOR will allow setting the default color to 0.
'
SUB BCOLOR(CL)
C=CL
IF C<0 THEN C=7
DEFLTC=C
END SUB
'
' BLOCATE emulates QB's LOCATE statement. R is the row and C is the
' column.
'
SUB BLOCATE(R,C,INREGS AS REGISTERS,OUTREGS AS REGISTERS)
INREGS.AX=&H200
'
' Get page number to print to.
'
INREGS.BX=CINT(ACPAGE)
'
' Bios row and column numbers are zero-based.
'
INREGS.DX=256*CINT(R-1)+CINT(C-1)
CALL INTERRUPTX(&H10,INREGS,OUTREGS)
END SUB
'
' BPRINT is the bios emulator for QB's PRINT statement. It prints the
' input character string STRNG$ at the current cursor position. It does
' not give a perfect emulation. Semicolons and commas within STRNG$ are
' printed like any other character. A semicolon at the end of STRNG$,
' however, suspends CR/LF printing just as with PRINT. Hence, consecutive
' BPRINT CALLs can be made to achieve the same affect as with PRINT with
' embedded ";" characters. Similarly, a comma at the end of STRNG$
' suppresses CR/LF printing and positions the cursor for the next BPRINT
' operation on the same line but at column (column after last character
' printed + 14) MOD 14, i.e., it attempts to emulate what an embedded
' comma in a PRINT statement would do. STRNG$ can be a maximum of 126
' characters. (It may be noted that QB functions such as STR$ and HEX$
' can be concatenated with other text to create most any string involving
' whatever numeric output you want.)
'
SUB BPRINT(STRNG$,INREGS AS REGISTERS,OUTREGS AS REGISTERS)
DIM A(1 TO 32) AS LONG,ROW AS INTEGER,COL AS INTEGER,BYTE AS INTEGER
DIM L AS INTEGER
'
' Make various initializations. (For one, STRNG$ is aliased with S$.)
'
SM=VARSEG(A(1)) : OS=VARPTR(A(1)) : INREGS.BP=CINT(OS) : S$=STRNG$ : L=LEN(S$)
IF L=0 THEN S$=" " : L=1
IF L>126 THEN L=126
'
' S$ will be stored in array A. Point memory pointer there and
' transfer characters.
'
DEF SEG=SM
IF L>1 THEN
FOR I=1 TO L-1
BYTE=ASC(MID$(S$,I,1))
POKE OS,BYTE
OS=OS+1
NEXT I
END IF
'
' Look for ";" or "," at end of S$. Terminate stored string with CR/LF
' if these characters are absent. Adjust number of characters (L) to be
' printed accordingly.
'
BYTE=ASC(MID$(S$,L,1))
IF BYTE<>59 AND BYTE<>44 THEN
POKE OS,BYTE
OS=OS+1
POKE OS,13
OS=OS+1
POKE OS,10
L=L+2
ELSE
L=L-1
END IF
DEF SEG
'
' Get page to print to and current cursor location and then print string
' there with default color.
'
INREGS.AX=&H300
INREGS.BX=CINT(ACPAGE)
CALL INTERRUPTX(&H10,INREGS,OUTREGS)
INREGS.AX=&H1301
INREGS.BX=DEFLTC
INREGS.CX=L
INREGS.DX=OUTREGS.DX
INREGS.ES=CINT(SM)
CALL INTERRUPTX(&H10,INREGS,OUTREGS)
IF BYTE=44 THEN
INREGS.AX=&H300
INREGS.BX=CINT(ACPAGE)
CALL INTERRUPTX(&H10,INREGS,OUTREGS)
ROW=(OUTREGS.DX AND &HFF00)/256
COL=OUTREGS.DX AND &HFF
COL=COL+14
COL=14*INT(CSNG(COL+1)/14+.001)-1
INREGS.AX=&H200
INREGS.BX=CINT(ACPAGE)
INREGS.DX=256*ROW+COL
CALL INTERRUPTX(&H10,INREGS,OUTREGS)
END IF
END SUB
'
' This function is the analog of QB's POINT function. Unlike the other
' page-oriented routines, it reads data from the page being displayed.
' (QB's "POINT(number)" function is not emulated here.) (The pixel
' color attribute returned is a 2-byte integer.)
'
FUNCTION BPOINT%(XCOORD,YCOORD,INREGS AS REGISTERS,OUTREGS AS REGISTERS)
'
' Get displayed page.
'
INREGS.AX=&HF00
CALL INTERRUPTX(&H10,INREGS,OUTREGS)
'
' Translate (XCOORD,YCOORD) to screen coordinates and enforce viewport
' constraints.
'
X=XCOORD+VXL : Y=YCOORD+VYL
IF X<VXL THEN X=VXL
IF Y<VYL THEN Y=VYL
IF X>VXR THEN X=VXR
IF Y>VYR THEN Y=VYR
'
' Get color attribute of pixel at (X,Y).
'
INREGS.AX=&HD00
INREGS.BX=OUTREGS.BX
INREGS.CX=CINT(X)
INREGS.DX=CINT(Y)
CALL INTERRUPTX(&H10,INREGS,OUTREGS)
BPOINT=OUTREGS.AX AND &HFF
END FUNCTION
'
' This is the analog of QB's graphics VIEW statement. Input positive
' numbers for CL and BORDER to fill the viewport with color CL or draw
' a box around it with color BORDER. (Use BORDER <= 0 to avoid drawing a
' a border. Fill color is set to 0 if CL < 0.)
'
SUB BVIEW(XL,YL,XR,YR,CL,BORDER,INREGS AS REGISTERS,OUTREGS AS REGISTERS)
VXL=CINT(XL) : VYL=CINT(YL) : VXR=CINT(XR) : VYR=CINT(YR)
'
' Disallow plotting off-screen and make other reasonable enforcements.
'
IF VXL<0 THEN VXL=0
IF VYL<0 THEN VYL=0
IF VXR>HMAX THEN VXR=HMAX
IF VYR>VMAX THEN VYR=VMAX
IF VXL>HMAX THEN VXL=0
IF VYL>VMAX THEN VYL=0
IF VXR<0 THEN VXR=HMAX
IF VYR<0 THEN VYR=VMAX
IF VXR<=VXL THEN VXL=0 : VXR=HMAX
IF VYR<=VYL THEN VYL=0 : VYR=VMAX
'
' Process CL and BORDER arguments. (Save them in global variables for
' BCLS subroutine.)
'
VCOL=CL : IF VCOL<0 THEN VCOL=0
VBORD=BORDER
'
' Clear viewport (fill with VCOL) and then draw border if appropriate.
' (Send BLINE viewport coordinates--it will convert them back to screen
' coordinates.)
'
CALL BLINE(0!,0!,VXR-VXL,VYR-VYL,VCOL,"BF",INREGS,OUTREGS)
IF VBORD>0 THEN CALL BLINE(0!,0!,VXR-VXL,VYR-VYL,VBORD,"B",INREGS,OUTREGS)
END SUB
'
' This subroutine emulates QB's PAINT statement.
'
SUB BPAINT(XP,YP,CL,BORDER,INREGS AS REGISTERS,OUTREGS AS REGISTERS)
DIM CPIXEL AS INTEGER,I AS INTEGER,J AS INTEGER
C=CL : IF C<0 THEN C=DEFLTC
'
' Translate (XP,YP) to screen coordinates.
'
X=XP+VXL : Y=YP+VYL
'
' If (X,Y) isn't within viewport, don't do anything.
'
IF X<VXL OR Y<VYL OR X>VXR OR Y>VYR THEN GOTO LEAVE
'
' Set background color. (Painting will only occur if current pixel is
' set to this color, which will be zero unless a filled viewport is
' active.)
'
CBACK=VCOL : IF CBACK<0 THEN CBACK=0
'
' If (X,Y) is on border of area to be painted, no painting occurs.
'
INREGS.AX=&HD00
INREGS.BX=CINT(ACPAGE)
INREGS.CX=CINT(X)
INREGS.DX=CINT(Y)
CALL INTERRUPTX(&H10,INREGS,OUTREGS)
CPIXEL=OUTREGS.AX AND &HFF
IF CPIXEL<>CBACK THEN GOTO LEAVE
'
' Begin painting. Do points above input (X,Y) first.
'
IF CINT(Y)>=VYL THEN
FOR J=CINT(Y) TO VYL STEP -1
'
' Do points to right of input (X,Y) first.
'
IF CINT(X)<=VXR THEN
FOR I=CINT(X) TO VXR
'
' Get pixel color at point (I,J).
'
INREGS.AX=&HD00
INREGS.BX=CINT(ACPAGE)
INREGS.CX=I
INREGS.DX=J
CALL INTERRUPTX(&H10,INREGS,OUTREGS)
CPIXEL=OUTREGS.AX AND &HFF
'
' Paint interior/exterior pixel with paint color, border pixel with
' border color (for non-negative BORDER input), or move to next part of
' figure.
'
IF CPIXEL=CBACK THEN CALL BPSET(CSNG(I)-VXL,CSNG(J)-VYL,C,INREGS,OUTREGS)
IF CPIXEL<>CBACK THEN
IF BORDER>=0 THEN CALL BPSET(CSNG(I)-VXL,CSNG(J)-VYL,BORDER,INREGS,OUTREGS)
EXIT FOR
END IF
NEXT I
END IF
'
' Do points to left of input (X,Y).
'
IF CINT(X)-1>=VXL THEN
FOR I=CINT(X)-1 TO VXL STEP -1
INREGS.AX=&HD00
INREGS.BX=CINT(ACPAGE)
INREGS.CX=I
INREGS.DX=J
CALL INTERRUPTX(&H10,INREGS,OUTREGS)
CPIXEL=OUTREGS.AX AND &HFF
IF CPIXEL=CBACK THEN CALL BPSET(CSNG(I)-VXL,CSNG(J)-VYL,C,INREGS,OUTREGS)
IF CPIXEL<>CBACK THEN
IF BORDER>=0 THEN CALL BPSET(CSNG(I)-VXL,CSNG(J)-VYL,BORDER,INREGS,OUTREGS)
EXIT FOR
END IF
NEXT I
IF I=CINT(X)-1 THEN EXIT FOR
END IF
NEXT J
END IF
'
' Now do points below input (X,Y).
'
IF CINT(Y)+1<=VYR THEN
FOR J=CINT(Y)+1 TO VYR
IF CINT(X)<=VXR THEN
FOR I=CINT(X) TO VXR
INREGS.AX=&HD00
INREGS.BX=CINT(ACPAGE)
INREGS.CX=I
INREGS.DX=J
CALL INTERRUPTX(&H10,INREGS,OUTREGS)
CPIXEL=OUTREGS.AX AND &HFF
IF CPIXEL=CBACK THEN CALL BPSET(CSNG(I)-VXL,CSNG(J)-VYL,C,INREGS,OUTREGS)
IF CPIXEL<>CBACK THEN
IF BORDER>=0 THEN CALL BPSET(CSNG(I)-VXL,CSNG(J)-VYL,BORDER,INREGS,OUTREGS)
EXIT FOR
END IF
NEXT I
END IF
IF CINT(X)-1>=VXL THEN
FOR I=CINT(X)-1 TO VXL STEP -1
INREGS.AX=&HD00
INREGS.BX=CINT(ACPAGE)
INREGS.CX=I
INREGS.DX=J
CALL INTERRUPTX(&H10,INREGS,OUTREGS)
CPIXEL=OUTREGS.AX AND &HFF
IF CPIXEL=CBACK THEN CALL BPSET(CSNG(I)-VXL,CSNG(J)-VYL,C,INREGS,OUTREGS)
IF CPIXEL<>CBACK THEN
IF BORDER>=0 THEN CALL BPSET(CSNG(I)-VXL,CSNG(J)-VYL,BORDER,INREGS,OUTREGS)
EXIT FOR
END IF
NEXT I
IF I=CINT(X)-1 THEN EXIT FOR
END IF
NEXT J
END IF
LEAVE:
END SUB